﻿#region Copyright 2011 Mike Goatly
// This source is subject to the the MIT License (MIT)
// All rights reserved.
#endregion

namespace Lifti.Tests.Persistence.PageManagerTests.Transactional
{
    using System;
    using System.Transactions;
    using Lifti.Persistence;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Moq;

    /// <summary>
    /// Tests for reading a page from a transactional page manager.
    /// </summary>
    [TestClass]
    public class ReadingPage : TransactionalPageManagerTestBase
    {
        /// <summary>
        /// When reading pages, the transaction should be checked first to 
        /// see if the page has been affected by the transaction first, prior to checking
        /// the page cache or loading the page.
        /// </summary>
        [TestMethod]
        public void ShouldReadPageFromTransactionCacheIfItExistsThere()
        {
            // Setup
            var transactionalPage = new Mock<IDataPage>();
            var header = new Mock<IDataPageHeader>();
            transactionalPage.SetupGet(p => p.Header).Returns(header.Object);
            header.SetupGet(h => h.PageNumber).Returns(0);
            header.SetupGet(h => h.DataPageType).Returns(DataPageType.Items);
            header.SetupGet(h => h.EntryCount).Returns(2);

            this.TransactionLog.Setup(l => l.TryGetPage(0)).Returns(transactionalPage.Object);
            this.PageCache.Setup(p => p.GetCachedPage(It.Is<IDataPageHeader>(h => h.PageNumber == 0), It.IsAny<Func<IDataPageHeader, IDataPage>>())).Returns(transactionalPage.Object);

            using (var scope = new TransactionScope())
            {
                // First get and save of the page need to initialize the page in the transaction
                var page = this.PageManager.GetPage(0);
                this.PageManager.SavePage(page);

                // At this point the transaction log should not have had the page read from it
                this.TransactionLog.Verify(l => l.TryGetPage(0), Times.Never());
                this.PageCache.Verify(p => p.GetCachedPage(It.Is<IDataPageHeader>(h => h.PageNumber == 0), It.IsAny<Func<IDataPageHeader, IDataPage>>()), Times.Exactly(1));

                // Read the page again
                this.PageManager.GetPage(0);
            }

            // Verify the page read counts - the transaction log should now be 1 and the page cache should
            // still be 1.
            this.TransactionLog.Verify(l => l.TryGetPage(0), Times.Exactly(1));
            this.PageCache.Verify(p => p.GetCachedPage(It.Is<IDataPageHeader>(h => h.PageNumber == 0), It.IsAny<Func<IDataPageHeader, IDataPage>>()), Times.Exactly(1));
        }
    }
}
